#include "ScnsSt7789.c.h"

#if defined(SCNS_ST7789_ENABLE)&&SCNS_ST7789_ENABLE==1

#include "ScnsSmctp.h"
#include "ScnsTimer.h"

const ScnsBspSt7789Config scnsBspSt7789Config[SCNS_ST7789_MAX]={
    {
        .dir=0,
        .horizon=240,
        .vertical=320,
        .horizonBias=0,
        .verticalBias=0,
        .bgr=0,
        .reverseColor=0,
    },
};

//#define PARALLEL 8

#if defined(PARALLEL)

#define PTX_RST        D5
#define PTX_BL         D11
#define PTX_RD         D4
#define PTX_WR         D6
#define PTX_RS         D13
#define PTX_CS         D7
#define PTX_D0         E11
#define PTX_D1         E12
#define PTX_D2         E13
#define PTX_D3         E14
#define PTX_D4         E15
#define PTX_D5         D8
#define PTX_D6         D9
#define PTX_D7         D10

#else

#define PTX_SPI     SPI_3
#define PTX_SCL     SPI3_SCK_D4
#define PTX_MOSI    SPI3_MOSI_D6
#define PTX_MISO    SPI_MISO_NULL
#define PTX_CS      D7
#define PTX_DC      D5
#define PTX_RST     D13
#define PTX_BL      D11

#endif

ScnsStatus scnsBspSt7789Init(ScnsSt7789Enum stn)
{
#if defined(PARALLEL)
    gpio_init(PTX_WR,GPO,GPIO_LOW,GPO_PUSH_PULL);       // FSMC_NWE IPS200_WR
    afio_init(PTX_CS,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_NE4 IPS200_CS
    afio_init(PTX_RS,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_A23 IPS200_RS
    afio_init(PTX_RD,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_NOE IPS200_RD
    afio_init(PTX_D0,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_D0 IPS200_D0
    afio_init(PTX_D1,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_D1 IPS200_D1
    afio_init(PTX_D2,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_D2 IPS200_D2
    afio_init(PTX_D3,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_D3 IPS200_D3
    afio_init(PTX_D4,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_D4 IPS200_D4
    afio_init(PTX_D5,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_D5 IPS200_D5
    afio_init(PTX_D6,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_D6 IPS200_D6
    afio_init(PTX_D7,GPO,GPIO_AF12,GPO_AF_PUSH_PULL);   // FSMC_D7 IPS200_D7
    
    if(0==(RCC->AHB3ENR&(0x00000001)))
    {
        RCC->AHB3ENR|=(0x00000001);
        RCC->AHB3RSTR|=(0x00000001);
        RCC->AHB3RSTR&=~(0x00000001);
    }
    FSMC->SMTMGRSET[0]=0x000000C0;
    FSMC->SMCTLR=0x00000001;
    FSMC->SMSKR0=0x0000002b;
#else
    spi_init(PTX_SPI,SPI_MODE2,system_clock/2,PTX_SCL,PTX_MOSI,PTX_MISO,SPI_CS_NULL);
    gpio_init(PTX_DC,GPO,GPIO_LOW,GPO_PUSH_PULL);
    gpio_init(PTX_CS,GPO,GPIO_HIGH,GPO_PUSH_PULL);
#endif
    gpio_init(PTX_RST,GPO,GPIO_LOW,GPO_PUSH_PULL);      // RTS
    gpio_init(PTX_BL,GPO,GPIO_LOW,GPO_PUSH_PULL);       // BL
    return SCNS_STATUS_OK;
}

ScnsStatus scnsBspSt7789SetRst(ScnsSt7789Enum stn,uint8 dat)
{
    gpio_set_level(PTX_RST,dat);
    return SCNS_STATUS_OK;
}

ScnsStatus scnsBspSt7789SetCs(ScnsSt7789Enum stN,uint8 cs)
{
#if !defined(PARALLEL)
    gpio_set_level(PTX_CS,cs);
#endif
    return SCNS_STATUS_OK;
}

ScnsStatus scnsBspSt7789WReg(ScnsSt7789Enum stn,uint8 dat)
{
#if defined(PARALLEL)
    gpio_low(PTX_WR);
    *(volatile uint16*)(0x60000000)=((uint16)dat<<8);
    gpio_high(PTX_WR);
#else
    gpio_set_level(PTX_DC,0);
    spi_write_8bit(PTX_SPI,dat);
#endif
    return SCNS_STATUS_OK;
}

ScnsStatus scnsBspSt7789WData(ScnsSt7789Enum stn,uint8 dat)
{
#if defined(PARALLEL)
    gpio_low(PTX_WR);
    (*(volatile uint16*)(0x60080000)=(((uint16)dat&0x00FF)<<8));
    gpio_high(PTX_WR);
#else
    gpio_set_level(PTX_DC,1);
    spi_write_8bit(PTX_SPI,dat);
#endif
    return SCNS_STATUS_OK;
}

ScnsStatus scnsBspSt7789WData16S(ScnsSt7789Enum stn,uint16 dat[],uint32 len)
{
#if defined(PARALLEL)
    for(uint32 i=0;i<len;++i)
    {
#if defined(SCNS_BSP_ST7789_SWAP_UINT16)&&SCNS_BSP_ST7789_SWAP_UINT16==1
        scnsBspSt7789WData(stn,dat[i]);
        scnsBspSt7789WData(stn,dat[i]>>8);
#else
        scnsBspSt7789WData(stn,dat[i]>>8);
        scnsBspSt7789WData(stn,dat[i]);
#endif
    }
#else
    gpio_set_level(PTX_DC,1);
    spi_write_8bit_array(PTX_SPI,(uint8*)dat,len*2);
#endif
    return SCNS_STATUS_OK;
}

#if !defined(PARALLEL)
ScnsStatus scnsBspSt7789WData16SAsync(ScnsSt7789Enum stn,uint16 dat[],uint32 len)
{
    gpio_set_level(PTX_DC,1);
    spi_mosi_dma(PTX_SPI,(uint8*)dat,len*2,NULL,0,0);
    dma_finish_nvic_enable(spi_tx_dma[PTX_SPI],1);
    return SCNS_STATUS_OK;
}
#endif

ScnsStatus scnsBspSt7789SetBackgroundLight(ScnsSt7789Enum stn,ScnsLcdBackgroundLightStatus status)
{
    gpio_set_level(PTX_BL,status==SCNS_LCD_BACKGROUND_LIGHT_ON?1:0);
    return SCNS_STATUS_OK;
}

#endif
